﻿using HalconDotNet;
using MvCamCtrl.NET;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using thinger.VisionControlLib;
using thinger.VisionModels;
using thinger.VisitionDAL;

namespace thinger.VisionDemo
{

    public partial class FrmCalibration3 : Form
    {
        public FrmCalibration3(ZmotionEx zmotion)
        {
            InitializeComponent();

            this.zmotion = zmotion;

            this.dgv_Data.AutoGenerateColumns = false;

            this.lst_Info.Columns[1].Width = this.lst_Info.Width - this.lst_Info.Columns[0].Width - 30;

            halcon.HalconInitial(this.hWindowControl1, out hWindowHandle);

            hikHelper.ImageEvent += HikHelper_ImageEvent;

            this.cmb_CamList.Items.AddRange(hikHelper.DeviceList.ToArray());

            if (hikHelper.DeviceList.Count > 0)
            {
                this.cmb_CamList.SelectedIndex = 0;
            }

            InitialParam();

            this.FormClosing += FrmCalibration_FormClosing;
        }

        private void FrmCalibration_FormClosing(object sender, FormClosingEventArgs e)
        {
            hikHelper.StopGrab();
            hikHelper.CloseCamera();
        }

        private void HikHelper_ImageEvent(MvCamCtrl.NET.MyCamera.MV_DISPLAY_FRAME_INFO stDisplayInfo)
        {
            HOperatorSet.GenImage1Extern(out hImage, "byte", stDisplayInfo.nWidth, stDisplayInfo.nHeight, stDisplayInfo.pData, IntPtr.Zero);

            //显示全图
            HOperatorSet.GetImageSize(hImage, out ImageWidth, out ImageHeight);

            //设置窗体句柄的大小
            HOperatorSet.SetPart(hWindowHandle, 0, 0, ImageHeight - 1, ImageWidth - 1);

            //显示
            HOperatorSet.DispObj(hImage, hWindowHandle);
        }

        private ZmotionEx zmotion;

        //创建相机操作对象
        private HikHelper hikHelper = new HikHelper();

        //创建Halcon帮助对象
        private HalconHelper halcon = new HalconHelper();

        //创建模板帮助对象
        private ShapeModelHelper shapeModel = new ShapeModelHelper();

        //创建工具帮助对象
        private ToolsHelper tools = new ToolsHelper();

        //创建标定帮助对象
        private CalibrationHelper calibration = new CalibrationHelper();

        //创建一个HwindowHandle
        private HTuple hWindowHandle = new HTuple();

        //创建一个hImage
        private HObject hImage = new HObject();

        //图像的宽度和高度
        private HTuple ImageWidth, ImageHeight;

        private string SaveBasePath = Application.StartupPath + "\\SaveImage";

        private string ModelBasePath = Application.StartupPath + "\\Model";

        private string CalibrationBasePath = Application.StartupPath + "\\Calibration";

        //模板匹配的实体对象
        private MatchParams matchParams = new MatchParams();

        //圆查找的实体对象
        private CircleParams circleParams = new CircleParams();

        public HObject objDisp;            //显示图形容器

        //标定数据
        private List<CalibrationData> CalibrationDatas = new List<CalibrationData>();

        //手眼标定就是一个HomMat2D
        private HTuple homMat2D = new HTuple();


        /// <summary>
        /// 初始化参数
        /// </summary>
        private void InitialParam()
        {
            this.cmb_CircleTransition.DataSource = Enum.GetNames(typeof(CircleTransition));
            this.cmb_CirclePointSelect.DataSource = Enum.GetNames(typeof(CirclePointSelect));

            //初始化参数
            this.txt_Angle.Text = matchParams.startAngle.ToString();
            this.txt_Range.Text = matchParams.rangeAngle.ToString();
            this.txt_Overlap.Text = matchParams.overlap.ToString();
            this.txt_Score.Text = matchParams.score.ToString();
            this.txt_Greediness.Text = matchParams.greediness.ToString();
            this.txt_NumMatchs.Text = matchParams.numMatchs.ToString();


            this.txt_CircleElements.Text = circleParams.circle_Elements.ToString();
            this.txt_CircleThreshold.Text = circleParams.circle_Threshold.ToString();
            this.txt_CircleSigma.Text = circleParams.circle_Sigma.ToString();
            this.cmb_CircleTransition.Text = circleParams.circle_Transition;
            this.cmb_CirclePointSelect.Text = circleParams.circle_Point_Select;

        }


        #region 添加日志
        /// <summary>
        /// 当前时间
        /// </summary>
        private string CurrentTime
        {
            get { return DateTime.Now.ToString("HH:mm:ss"); }
        }

        /// <summary>
        /// 添加日志信息
        /// </summary>
        /// <param name="index">日志等级</param>
        /// <param name="log">日志信息</param>
        public void AddLog(int index, string log)
        {
            if (!this.lst_Info.InvokeRequired)
            {
                ListViewItem lst = new ListViewItem("   " + CurrentTime, index);
                lst.SubItems.Add(log);
                this.lst_Info.Items.Add(lst);
                this.lst_Info.Items[this.lst_Info.Items.Count - 1].EnsureVisible();
            }
            else
            {
                this.lst_Info.Invoke(new Action<int, string>(AddLog), index, log);
            }
        }
        #endregion

        #region 图像采集
        private void btn_SearchCam_Click(object sender, EventArgs e)
        {
            hikHelper.InitialCameraList();

            this.cmb_CamList.Items.Clear();
            this.cmb_CamList.Items.AddRange(hikHelper.DeviceList.ToArray());

            if (hikHelper.DeviceList.Count > 0)
            {
                this.cmb_CamList.SelectedIndex = 0;
            }
        }

        private void btn_Open_Click(object sender, EventArgs e)
        {
            if (cmb_CamList.SelectedIndex == -1)
            {
                AddLog(1, "请先选择要打开的相机");
                return;
            }

            //加载相机列表
            hikHelper.LoadCameraList(new List<string>() { this.cmb_CamList.Text });

            //打开相机
            var result = hikHelper.OpenCamera();

            if (result[0].IsSuccess)
            {
                AddLog(0, result[0].Message);

                this.tb_ExposureTime.Value = Convert.ToInt32(hikHelper.ExposureTime[0]);
                this.txt_ExposureTime.Text = hikHelper.ExposureTime[0].ToString("f1");

                this.tb_Gain.Value = Convert.ToInt32(hikHelper.Gain[0]);
                this.txt_Gain.Text = hikHelper.Gain[0].ToString("f1");

                this.tb_FrameRate.Value = Convert.ToInt32(hikHelper.FrameRate[0]);
                this.txt_FrameRate.Text = hikHelper.FrameRate[0].ToString("f1");
            }
            else
            {
                AddLog(1, result[0].Message);
            }
        }

        private void btn_Close_Click(object sender, EventArgs e)
        {
            hikHelper.StopGrab();
            this.btn_StartGrab.Enabled = true;
            this.btn_StopGrab.Enabled = false;

            hikHelper.CloseCamera();
            AddLog(0, "相机关闭成功");
        }

        private void btn_StartGrab_Click(object sender, EventArgs e)
        {
            hikHelper.StartGrab();
            this.btn_StartGrab.Enabled = false;
            this.btn_StopGrab.Enabled = true;
            AddLog(0, "开始采集");
        }

        private void btn_StopGrab_Click(object sender, EventArgs e)
        {
            hikHelper.StopGrab();
            this.btn_StartGrab.Enabled = true;
            this.btn_StopGrab.Enabled = false;
            AddLog(0, "停止采集");
        }

        private void btn_TriggerExec_Click(object sender, EventArgs e)
        {
            hikHelper.TriggerExec();
        }

        private void tb_ExposureTime_Scroll(object sender, EventArgs e)
        {
            if (hikHelper.SetExposureTime(this.tb_ExposureTime.Value) == 0)
            {
                this.txt_ExposureTime.Text = this.tb_ExposureTime.Value.ToString();
            }
            else
            {
                AddLog(1, "曝光时间设置失败");
            }
        }

        private void tb_Gain_Scroll(object sender, EventArgs e)
        {
            if (hikHelper.SetGain(this.tb_Gain.Value) == 0)
            {
                this.txt_Gain.Text = this.tb_Gain.Value.ToString();
            }
            else
            {
                AddLog(1, "增益设置失败");
            }
        }

        private void tb_FrameRate_Scroll(object sender, EventArgs e)
        {
            if (hikHelper.SetFrameRate(this.tb_FrameRate.Value) == 0)
            {
                this.txt_FrameRate.Text = this.tb_FrameRate.Value.ToString();
            }
            else
            {
                AddLog(1, "帧率设置失败");
            }
        }

        private void rdb_ContinuesMode_CheckedChanged(object sender, EventArgs e)
        {
            if (hikHelper.SetTriggerMode(MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF) == 0)
            {
                this.chk_SoftTrigger.Enabled = false;
                this.btn_TriggerExec.Enabled = false;
            }
        }

        private void rdb_TriggerMode_CheckedChanged(object sender, EventArgs e)
        {
            if (hikHelper.SetTriggerMode(MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON) == 0)
            {
                this.chk_SoftTrigger.Enabled = true;
                this.btn_TriggerExec.Enabled = true;
            }
        }

        private void chk_SoftTrigger_CheckedChanged(object sender, EventArgs e)
        {
            if (this.chk_SoftTrigger.Checked)
            {
                hikHelper.SetTriggerSource(MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
            }
            else
            {
                hikHelper.SetTriggerSource(MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
            }
        }

        private void btn_SaveBmp_Click(object sender, EventArgs e)
        {
            hikHelper.SaveImage(MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Bmp, SaveBasePath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".bmp");
        }

        private void btn_SaveJpg_Click(object sender, EventArgs e)
        {
            hikHelper.SaveImage(MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Jpeg, SaveBasePath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".jpg");
        }

        private void btn_SaveTiff_Click(object sender, EventArgs e)
        {
            hikHelper.SaveImage(MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Tif, SaveBasePath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".tif");
        }

        private void btn_SavePng_Click(object sender, EventArgs e)
        {
            hikHelper.SaveImage(MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Png, SaveBasePath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".png");
        }

        private void btn_OpenImage_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = ".bmp|*.bmp|.png|*.png|.jpg|*.jpg|.tif|*.tif|.jpeg|*.jpeg";

                openFileDialog.Multiselect = false;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string path = openFileDialog.FileName;

                    var result = halcon.ReadImage(path, this.hWindowHandle, out hImage, out ImageWidth, out ImageHeight);

                    if (result.IsSuccess)
                    {
                        AddLog(0, "打开图像成功");
                    }
                    else
                    {
                        AddLog(1, "打开图像失败：" + result.Message);
                    }
                }
            }
        }


        #endregion

        #region 模板匹配
        private void btn_CreateShapeModel_Click(object sender, EventArgs e)
        {
            //控件焦点
            this.hWindowControl1.Focus();

            //设置参数
            matchParams.startAngle = Convert.ToSingle(this.txt_Angle.Text);
            matchParams.rangeAngle = Convert.ToSingle(this.txt_Range.Text);

            var result = shapeModel.CreateShapeModel(hWindowHandle, hImage, matchParams);

            if (result.IsSuccess)
            {
                //获取轮廓
                HOperatorSet.GetShapeModelContours(out HObject contour, matchParams.modelId, 1);
                //显示轮廓
                HOperatorSet.DispObj(contour, hWindowHandle);

                AddLog(0, "创建模板成功");
            }
            else
            {
                AddLog(1, "创建模板失败：" + result.Message);
            }
        }

        private void btn_FindShapeModel_Click(object sender, EventArgs e)
        {
            if (matchParams.modelId == null)
            {
                AddLog(1, "查找模板失败：模板不存在");
                return;
            }

            this.hWindowControl1.Focus();

            //参数赋值
            matchParams.startAngle = Convert.ToDouble(this.txt_Angle.Text.Trim());
            matchParams.rangeAngle = Convert.ToDouble(this.txt_Range.Text.Trim());
            matchParams.overlap = Convert.ToDouble(this.txt_Overlap.Text.Trim());
            matchParams.score = Convert.ToDouble(this.txt_Score.Text.Trim());
            matchParams.numMatchs = Convert.ToInt32(this.txt_NumMatchs.Text.Trim());
            matchParams.greediness = Convert.ToDouble(this.txt_Greediness.Text.Trim());

            var result = shapeModel.FindShapeModel(hWindowHandle, hImage, matchParams, out HTuple homMat2D);

            if (result.IsSuccess)
            {
                AddLog(0, "查找模板成功");
            }
            else
            {
                AddLog(1, "查找模板失败：" + result.Message);
            }
        }

        private void btn_SaveShapeModel_Click(object sender, EventArgs e)
        {
            //判断
            if (this.txt_ModelName.Text.Trim().Length == 0)
            {
                MessageBox.Show("模板名称不能为空", "保存模板");
                return;
            }

            if (shapeModel.GetAllShapeModels(ModelBasePath).Contains(this.txt_ModelName.Text.Trim()))
            {
                DialogResult dialogResult = MessageBox.Show("模板名称已经存在，是否覆盖？", "创建模板", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                if (dialogResult == DialogResult.No)
                {
                    return;
                }
            }

            //文件夹路径
            string path = ModelBasePath + "\\" + this.txt_ModelName.Text.Trim();

            //如果包含，删除
            if (Directory.Exists(path))
            {
                DirectoryInfo directoryInfo = new DirectoryInfo(path);

                directoryInfo.Delete(true);
            }

            //能够走到这个地方，肯定这个文件要么本来就没有，要么已经被删除了

            //创建文件夹
            Directory.CreateDirectory(path);

            //保存模板
            var result = shapeModel.SaveShapeModel(path, matchParams, circleParams);

            if (result.IsSuccess)
            {
                AddLog(0, "模板保存成功,模板名称：" + this.txt_ModelName.Text.Trim());
            }
            else
            {
                AddLog(1, "模板保存失败：" + result.Message);
            }
        }

        #endregion

        #region 查找圆

        private void btn_CircleROI_Click(object sender, EventArgs e)
        {
            this.hWindowControl1.Focus();

            halcon.draw_spoke3(hImage, out HObject hRegions, hWindowHandle, circleParams.circle_Elements, circleParams.circle_Caliper_Height, circleParams.circle_Caliper_Width, out circleParams.rOI_Y, out circleParams.rOI_X, out circleParams.circle_Direct);

            if (circleParams.rOI_X.Length < 4)
            {
                halcon.disp_message(hWindowHandle, "画圆ROI失败", "window", 20, 20, "red", "false");

                AddLog(1, "创建ROI失败");
            }

            else
            {
                HOperatorSet.DispObj(hImage, hWindowHandle);
                HOperatorSet.DispObj(hRegions, hWindowHandle);
                halcon.disp_message(hWindowHandle, "画圆ROI成功", "window", 20, 20, "green", "false");
                AddLog(0, "创建ROI成功");
            }
        }


        private void btn_FindCircle_Click(object sender, EventArgs e)
        {
            circleParams.circle_Elements = Convert.ToInt32(this.txt_CircleElements.Text.Trim());
            circleParams.circle_Threshold = Convert.ToInt32(this.txt_CircleThreshold.Text.Trim());
            circleParams.circle_Sigma = Convert.ToInt32(this.txt_CircleSigma.Text.Trim());
            circleParams.circle_Transition = this.cmb_CircleTransition.Text;
            circleParams.circle_Point_Select = this.cmb_CirclePointSelect.Text;

            var result = tools.FindCircle(hWindowHandle, hImage, matchParams, ref circleParams);

            if (result.IsSuccess)
            {
                string pos = circleParams.circleCenter_X.D.ToString("f2") + "," + circleParams.circleCenter_Y.D.ToString("f2");

                AddLog(0, "圆查找成功：" + pos);
            }
            else
            {
                AddLog(1, "圆查找失败：" + result.Message);
            }
        }


        #endregion

        #region 九点标定

        private void btn_RefreshShapeModel_Click(object sender, EventArgs e)
        {
            this.cmb_ModelList.Items.Clear();
            var list = shapeModel.GetAllShapeModels(ModelBasePath);

            if (list.Count > 0)
            {
                this.cmb_ModelList.Items.AddRange(list.ToArray());
                this.cmb_ModelList.SelectedIndex = 0;
            }
        }


        private void RefreshCalibrationData()
        {
            if (this.dgv_Data.InvokeRequired)
            {
                this.dgv_Data.Invoke(new Action(RefreshCalibrationData));
            }
            else
            {
                this.dgv_Data.DataSource = null;
                this.dgv_Data.DataSource = this.CalibrationDatas;
            }
        }

        private void btn_SaveCalibration_Click(object sender, EventArgs e)
        {
            //判断
            if (this.txt_CalibrationName.Text.Trim().Length == 0)
            {
                MessageBox.Show("标定名称不能为空", "保存标定");
                return;
            }

            if (calibration.GetAllCalibrations(CalibrationBasePath).Contains(this.txt_CalibrationName.Text.Trim()))
            {
                DialogResult dialogResult = MessageBox.Show("标定名称已经存在，是否覆盖？", "保存标定", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                if (dialogResult == DialogResult.No)
                {
                    return;
                }
            }

            //文件夹路径
            string path = CalibrationBasePath + "\\" + this.txt_CalibrationName.Text.Trim();


            //如果包含，删除
            if (Directory.Exists(path))
            {
                DirectoryInfo directoryInfo = new DirectoryInfo(path);

                directoryInfo.Delete(true);
            }

            //创建文件夹
            Directory.CreateDirectory(path);

            CalibrationInfo calibrationInfo = new CalibrationInfo();
            calibrationInfo.HomMat2D = this.homMat2D;
            calibrationInfo.CalibrationDatas = this.CalibrationDatas;
            calibrationInfo.PositionInfo = GetPositionInfo();
            var result = calibration.SaveCalibration(path, calibrationInfo);

            if (result.IsSuccess)
            {
                AddLog(0, "标定数据保存成功,模板名称：" + this.txt_CalibrationName.Text.Trim());
            }
            else
            {
                AddLog(1, "标定数据保存失败：" + result.Message);
            }
        }

        private void btn_RefreshCalibration_Click(object sender, EventArgs e)
        {
            this.cmb_Calibration.Items.Clear();
            var list = calibration.GetAllCalibrations(CalibrationBasePath);

            if (list.Count > 0)
            {
                this.cmb_Calibration.Items.AddRange(list.ToArray());
                this.cmb_Calibration.SelectedIndex = 0;
            }
        }

        private void btn_LoadCalibration_Click(object sender, EventArgs e)
        {
            string path = CalibrationBasePath + "\\" + this.cmb_Calibration.Text.Trim();

            var result = calibration.LoadCalibration(path);

            if (result.IsSuccess)
            {
                this.CalibrationDatas = result.Content.CalibrationDatas;

                RefreshCalibrationData();

                this.homMat2D = result.Content.HomMat2D;

                SetPositionInfo(result.Content.PositionInfo);

                AddLog(0, "标定加载成功：" + this.cmb_Calibration.Text.Trim());
            }
            else
            {
                AddLog(1, "标定加载失败：" + result.Message);
            }
        }



        private void btn_Del_Click(object sender, EventArgs e)
        {
            if (this.dgv_Data.SelectedRows.Count > 0)
            {
                int index = this.dgv_Data.SelectedRows[0].Index;

                this.CalibrationDatas.RemoveAt(index);

                RefreshCalibrationData();
            }
            else
            {
                AddLog(1, "请先选中要删除的数据");
            }
        }




        private void btn_Calibration_Click(object sender, EventArgs e)
        {
            var result = calibration.Calibration(this.CalibrationDatas);

            if (result.IsSuccess)
            {
                this.homMat2D = result.Content;
                AddLog(0, "九点标定成功");
            }
            else
            {
                AddLog(1, "九点标定失败：" + result.Message);
            }
        }

        private void btn_Verify_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
                {
                    VerifyControl(16.2f, 1, true);
                });
        }


        /// <summary>
        /// 验证
        /// </summary>
        /// <param name="putZ">Z轴取料位置</param>
        /// <param name="xzNo">吸嘴编号：控制不同的Z轴</param>
        /// <param name="isGet">是否取料：控制不同的光源</param>
        private void VerifyControl(float putZ, int xzNo, bool isGet)
        {
            //开光源
            var result = isGet ? zmotion.GetGYOpen() : zmotion.PutGYOpen();

            //触发拍照
            hikHelper.TriggerExec();
            Thread.Sleep(500);

            //关光源
            result = isGet ? zmotion.GetGYClose() : zmotion.PutGYClose();

            //图像保存
            hikHelper.SaveImage(MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Bmp, SaveBasePath + $"\\验证{DateTime.Now.ToString("yyyyMMddHHmmss")}.bmp");

            //查找圆
            result = tools.FindCircle(hWindowHandle, hImage, matchParams, ref circleParams);

            if (result.IsSuccess == false)
            {
                AddLog(1, "【验证】查找圆失败：" + result.Message);
                return;
            }

            //获取图像坐标
            float imageX = Convert.ToSingle(circleParams.circleCenter_X.D);
            float imageY = Convert.ToSingle(circleParams.circleCenter_Y.D);

            //仿射变换，获取物理坐标
            HOperatorSet.AffineTransPoint2d(homMat2D, imageX, imageY, out HTuple posX, out HTuple posY);

            //XY运动
            zmotion.MoveXY(Convert.ToSingle(posX.D), Convert.ToSingle(posY.D));

            //Z轴动

            bool isZ1 = xzNo == 1;

            result = isZ1 ? zmotion.MoveZ1(putZ) : zmotion.MoveZ2(putZ);

            //吸气
            result = isZ1 ? zmotion.XQZ1() : zmotion.XQZ2();
            Thread.Sleep(500);

            //Z轴回归
            result = isZ1 ? zmotion.MoveZ1(0.0f) : zmotion.MoveZ2(0.0f);

            //XY运动
            zmotion.MoveXY(10.0f, 10.0f);

            //Z轴动
            result = isZ1 ? zmotion.MoveZ1(putZ) : zmotion.MoveZ2(putZ);

            //放气
            result = isZ1 ? zmotion.FQZ1() : zmotion.FQZ2();
            Thread.Sleep(500);

            zmotion.ZeroAll();
        }




        private void btn_LoadShapeModel_Click(object sender, EventArgs e)
        {
            string path = ModelBasePath + "\\" + this.cmb_ModelList.Text.Trim();

            var result = shapeModel.LoadShapeModel(path);

            if (result.IsSuccess)
            {
                this.matchParams = result.Content1;
                this.circleParams = result.Content2;
                AddLog(0, "模板加载成功：" + this.cmb_ModelList.Text.Trim());
            }
            else
            {
                AddLog(1, "模板加载失败");
            }
        }


        /// <summary>
        /// 获取位置信息
        /// </summary>
        /// <returns></returns>
        private PositionInfo GetPositionInfo()
        {
            return new PositionInfo()
            {
                GetX = Convert.ToSingle(this.num_GetX.Value),
                GetY = Convert.ToSingle(this.num_GetY.Value),
                StartX = Convert.ToSingle(this.num_StartX.Value),
                StartY = Convert.ToSingle(this.num_StartY.Value),
                MoveX = Convert.ToSingle(this.num_MoveX.Value),
                MoveY = Convert.ToSingle(this.num_MoveY.Value),
                GetZ = Convert.ToSingle(this.num_GetZ.Value),
                PutZ = Convert.ToSingle(this.num_PutZ.Value)
            };
        }
        /// <summary>
        /// 更新位置信息
        /// </summary>
        /// <param name="positionInfo"></param>
        private void SetPositionInfo(PositionInfo positionInfo)
        {
            this.num_GetX.Value = Convert.ToDecimal(positionInfo.GetX);
            this.num_GetY.Value = Convert.ToDecimal(positionInfo.GetY);

            this.num_StartX.Value = Convert.ToDecimal(positionInfo.StartX);
            this.num_StartY.Value = Convert.ToDecimal(positionInfo.StartY);

            this.num_MoveX.Value = Convert.ToDecimal(positionInfo.MoveX);
            this.num_MoveY.Value = Convert.ToDecimal(positionInfo.MoveY);

            this.num_GetZ.Value = Convert.ToDecimal(positionInfo.GetZ);
            this.num_PutZ.Value = Convert.ToDecimal(positionInfo.PutZ);
        }


        private void btn_Excute_Click(object sender, EventArgs e)
        {
            int PosIndex = Convert.ToInt32(this.num_No.Value);

            PositionInfo positionInfo = GetPositionInfo();

            int XZNo = Convert.ToInt32(this.num_XZ.Value);

            bool IsGet = this.rdb_Get.Checked;

            ClearState();

            Task.Run(() =>
            {
                var result = UpCameraCalibration(PosIndex, positionInfo, XZNo, IsGet);

                if (result.IsSuccess)
                {
                    AddLog(0, "标定完成");
                }
                else
                {
                    AddLog(1, "标定失败：" + result.Message);
                }
            });
        }

        /// <summary>
        /// 上相机标定流程
        /// </summary>
        /// <param name="posIndex"></param>
        /// <param name="info"></param>
        /// <param name="xzNo"></param>
        /// <param name="isGet"></param>
        /// <returns></returns>
        private OperateResult UpCameraCalibration(int posIndex, PositionInfo info, int xzNo, bool isGet)
        {
            var posRes = GetPosition(posIndex, info);

            //1、执行回原点

            this.excuteState1.State = State.Excute;

            var result = posIndex == 1 ? zmotion.ZeroAll() : OperateResult.CreateSuccessResult();

            if (result.IsSuccess == false)
            {
                this.excuteState1.State = State.Error;
                return result;
            }

            this.excuteState1.State = State.Done;

            //2、运行到取料位

            this.excuteState2.State = State.Excute;

            result = zmotion.MoveXY(posRes.Content2.X, posRes.Content2.Y);

            if (result.IsSuccess == false)
            {
                this.excuteState2.State = State.Error;
                return result;
            }
            this.excuteState2.State = State.Done;

            //3、取料   Z轴运动+吸取+回来
            this.excuteState3.State = State.Excute;

            result = xzNo == 1 ? zmotion.MoveZ1(posRes.Content3) : zmotion.MoveZ2(posRes.Content3);

            if (result.IsSuccess == false)
            {
                this.excuteState3.State = State.Error;
                return result;
            }

            result = xzNo == 1 ? zmotion.XQZ1() : zmotion.XQZ2();

            Thread.Sleep(100);

            result = xzNo == 1 ? zmotion.MoveZ1(0.0F) : zmotion.MoveZ2(0.0F);

            if (result.IsSuccess == false)
            {
                this.excuteState3.State = State.Error;
                return result;
            }

            this.excuteState3.State = State.Done;

            //4、运行到放料位

            this.excuteState4.State = State.Excute;

            result = zmotion.MoveXY(posRes.Content1.X, posRes.Content1.Y);

            if (result.IsSuccess == false)
            {
                this.excuteState4.State = State.Error;
                return result;
            }
            this.excuteState4.State = State.Done;

            //5、放料

            this.excuteState5.State = State.Excute;

            result = xzNo == 1 ? zmotion.MoveZ1(posRes.Content4) : zmotion.MoveZ2(posRes.Content4);

            if (result.IsSuccess == false)
            {
                this.excuteState5.State = State.Error;
                return result;
            }

            result = xzNo == 1 ? zmotion.FQZ1() : zmotion.FQZ2();

            Thread.Sleep(100);

            result = xzNo == 1 ? zmotion.MoveZ1(0.0F) : zmotion.MoveZ2(0.0F);

            if (result.IsSuccess == false)
            {
                this.excuteState5.State = State.Error;
                return result;
            }

            this.excuteState5.State = State.Done;

            //6、回原点（只要是不影响拍照就可以）

            this.excuteState6.State = State.Excute;

            result = isGet ? zmotion.MoveXY(0.0f, 0.0f) : zmotion.MoveXY(38f, 180f);

            if (result.IsSuccess == false)
            {
                this.excuteState6.State = State.Error;
                return result;
            }

            this.excuteState6.State = State.Done;

            //7、图像处理

            this.excuteState7.State = State.Excute;

            //开光源
            result = isGet ? zmotion.GetGYOpen() : zmotion.PutGYOpen();
            //触发拍照
            hikHelper.TriggerExec();
            Thread.Sleep(100);
            result = isGet ? zmotion.GetGYClose() : zmotion.PutGYClose(); ;

            result = tools.FindCircle(hWindowHandle, hImage, matchParams, ref circleParams);

            if (result.IsSuccess == false)
            {
                this.excuteState7.State = State.Error;
                return result;
            }
            else
            {
                float imageX = Convert.ToSingle(circleParams.circleCenter_X.D);
                float imageY = Convert.ToSingle(circleParams.circleCenter_Y.D);

                this.CalibrationDatas.Add(new CalibrationData()
                {
                    ImageX = imageX,
                    ImageY = imageY,
                    PositionX = posRes.Content1.X,
                    PositionY = posRes.Content1.Y
                });

                RefreshCalibrationData();
            }

            this.excuteState7.State = State.Done;

            ClearState();

            return OperateResult.CreateSuccessResult();

        }

        /// <summary>
        /// 下相机标定流程
        /// </summary>
        /// <param name="info"></param>
        /// <param name="xzNo"></param>
        /// <returns></returns>
        private OperateResult DownCameraCalibration(PositionInfo info, int xzNo)
        {
            //回零
            var result = zmotion.ZeroAll();

            if (result.IsSuccess == false) return result;

            //获取目标位置
            var posRes = GetPosition(1, info);

            //取料

            //运动到正上面
            result = zmotion.MoveXY(posRes.Content2.X, posRes.Content2.Y);
            if (result.IsSuccess == false) return result;

            //Z轴下降
            result = xzNo == 1 ? zmotion.MoveZ1(posRes.Content3) : zmotion.MoveZ2(posRes.Content3);

            //吸气
            result = xzNo == 1 ? zmotion.XQZ1() : zmotion.XQZ2();

            //Z轴上升
            result = xzNo == 1 ? zmotion.MoveZ1(posRes.Content4) : zmotion.MoveZ2(posRes.Content4);

            for (int i = 1; i <=9; i++)
            {
                 posRes = GetPosition(i, info);

                //运行到某个位置
                result = zmotion.MoveXY(posRes.Content1.X, posRes.Content1.Y);

                //触发拍照

                result = zmotion.DownGYOpen();

                hikHelper.TriggerExec();

                Thread.Sleep(500);

                result = zmotion.DownGYClose();

                result = tools.FindCircle(this.hWindowHandle, this.hImage, matchParams, ref circleParams);

                Thread.Sleep(1000);

                if (result.IsSuccess == false)
                {
                    return result;
                }
                else
                {
                    float imageX = Convert.ToSingle(circleParams.circleCenter_X.D);
                    float imageY = Convert.ToSingle(circleParams.circleCenter_Y.D);

                    this.CalibrationDatas.Add(new CalibrationData()
                    {
                        ImageX = imageX,
                        ImageY = imageY,
                        PositionX = posRes.Content1.X,
                        PositionY = posRes.Content1.Y
                    });

                    RefreshCalibrationData();
                }
            }

            posRes = GetPosition(1, info);

            //将产品放回去
       
            result = zmotion.MoveXY(posRes.Content2.X, posRes.Content2.Y);
            if (result.IsSuccess == false) return result;

            //Z轴下降
            result = xzNo == 1 ? zmotion.MoveZ1(posRes.Content3) : zmotion.MoveZ2(posRes.Content3);
            if (result.IsSuccess == false) return result;

            //吸气
            result = xzNo == 1 ? zmotion.FQZ1() : zmotion.FQZ2();

            result = zmotion.ZeroAll();
            if (result.IsSuccess == false) return result;

            return OperateResult.CreateSuccessResult();

        }


        /// <summary>
        /// 手动清除状态
        /// </summary>
        private void ClearState()
        {
            //先手动清除状态
            this.excuteState1.State = State.None;
            this.excuteState2.State = State.None;
            this.excuteState3.State = State.None;
            this.excuteState4.State = State.None;
            this.excuteState5.State = State.None;
            this.excuteState6.State = State.None;
            this.excuteState7.State = State.None;
        }

        private void btn_Auto_Click(object sender, EventArgs e)
        {
            PositionInfo positionInfo = GetPositionInfo();

            int XZNo = Convert.ToInt32(this.num_XZ.Value);

            bool IsGet = this.rdb_Get.Checked;

            ClearState();

            var task = Task.Run(() =>
            {
                //如果是下相机标定
                if (this.rdb_Down.Checked)
                {
                    DownCameraCalibration(positionInfo, XZNo);
                }
                else
                {
                    for (int i = 1; i <= 9; i++)
                    {
                        var result = UpCameraCalibration(i, positionInfo, XZNo, IsGet);

                        if (result.IsSuccess)
                        {
                            AddLog(0, $"第{i}次标定成功");
                        }
                        else
                        {
                            AddLog(1, $"第{i}次标定失败：" + result.Message);
                            return;
                        }
                    }
                }
            });

            task.ContinueWith(task2 =>
            {
                //九点标定

                var result = calibration.Calibration(this.CalibrationDatas);

                if (result.IsSuccess)
                {
                    AddLog(0, $"九点标定成功");
                }
                else
                {
                    AddLog(1, $"九点标定失败：" + result.Message);
                    return;
                }

            });
        }

        private void btn_StopAll_Click(object sender, EventArgs e)
        {
            zmotion.StopAllAxis();
        }



        /// <summary>
        /// 第一个返回值PointF，放料位的坐标
        /// 第二个返回值PointF，取料位的坐标
        /// 取料位的Z
        /// 放料位的Z
        /// </summary>
        /// <param name="posIndex"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        private OperateResult<PointF, PointF, float, float> GetPosition(int posIndex, PositionInfo info)
        {
            switch (posIndex)
            {
                case 1: return OperateResult.CreateSuccessResult(new PointF(info.StartX, info.StartY), new PointF(info.GetX, info.GetY), info.GetZ, info.PutZ);
                case 2: return OperateResult.CreateSuccessResult(new PointF(info.StartX - info.MoveX, info.StartY), new PointF(info.StartX, info.StartY), info.PutZ, info.PutZ);
                case 3: return OperateResult.CreateSuccessResult(new PointF(info.StartX - info.MoveX, info.StartY + info.MoveY), new PointF(info.StartX - info.MoveX, info.StartY), info.PutZ, info.PutZ);
                case 4: return OperateResult.CreateSuccessResult(new PointF(info.StartX, info.StartY + info.MoveY), new PointF(info.StartX - info.MoveX, info.StartY + info.MoveY), info.PutZ, info.PutZ);
                case 5: return OperateResult.CreateSuccessResult(new PointF(info.StartX + info.MoveX, info.StartY + info.MoveY), new PointF(info.StartX, info.StartY + info.MoveY), info.PutZ, info.PutZ);
                case 6: return OperateResult.CreateSuccessResult(new PointF(info.StartX + info.MoveX, info.StartY), new PointF(info.StartX + info.MoveX, info.StartY + info.MoveY), info.PutZ, info.PutZ);
                case 7: return OperateResult.CreateSuccessResult(new PointF(info.StartX + info.MoveX, info.StartY - info.MoveY), new PointF(info.StartX + info.MoveX, info.StartY), info.PutZ, info.PutZ);
                case 8: return OperateResult.CreateSuccessResult(new PointF(info.StartX, info.StartY - info.MoveY), new PointF(info.StartX + info.MoveX, info.StartY - info.MoveY), info.PutZ, info.PutZ);
                case 9: return OperateResult.CreateSuccessResult(new PointF(info.StartX - info.MoveX, info.StartY - info.MoveY), new PointF(info.StartX, info.StartY - info.MoveY), info.PutZ, info.PutZ);
                default: return OperateResult.CreateFailResult<PointF, PointF, float, float>("位置范围超限");
            }
        }


        #endregion
    }
}
